import { Injectable } from '@angular/core';
import { Action, NgxsAfterBootstrap, State, StateContext } from '@ngxs/store';
import { ShopAction } from './shop.action';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ModalComponent } from '@shop/modal/modal.component';
import { ResetForm } from '@ngxs/form-plugin';
import { tap } from 'rxjs';
import * as immutable from 'object-path-immutable';
import * as _ from 'lodash';
import { MessageAction } from '@shared/lib/store/message/message.action';
import { ShopService } from '@shop/shop.service';
import { uuid } from '@shared/lib/utils/utils';

export interface ShopStateModel {
  form: any;
  formFlag: boolean;
  list: any;
  cart: any;
}

@State<ShopStateModel>({
  name: 'shop',
  defaults: {
    form: {},
    formFlag: true,
    list: [],
    cart: {},
  },
})
@Injectable({
  providedIn: 'root',
})
export class ShopState implements NgxsAfterBootstrap {

  constructor(
      private modal: NzModalService,
      private shopService: ShopService,
  ) {
  }

  ngxsAfterBootstrap(ctx: StateContext<any>): void {
    ctx.patchState({formFlag: false});
    this.shopService.init();
  }

  @Action(ShopAction.Submit)
  Submit(ctx: StateContext<ShopStateModel>) {
    let state = ctx.getState();
    if (!state.form.dirty || state.form.status !== 'VALID') return;
    let model = state.form.model;
    if (!model.id) {
      model.id = uuid();
      ctx.setState(immutable.insert(state, ['list'], model));
    } else {
      let idx = _.findIndex(state.list, (s: any) => s.id === model.id);
      ctx.setState(immutable.set(state, ['list', idx], model));
    }
    ctx.patchState({formFlag: false});
  }

  @Action(ShopAction.CloseModal)
  CloseModal(ctx: StateContext<ShopStateModel>) {
    ctx.patchState({formFlag: false});
  }

  @Action(ShopAction.OpenModal)
  OpenModal(ctx: StateContext<ShopStateModel>, {data}: ShopAction.OpenModal) {
    return ctx.dispatch(new ResetForm({path: 'shop.form', value: data})).pipe(tap(() => {
      ctx.patchState({formFlag: true});
      let modalRef: any = this.modal.create({
        nzTitle: data ? '编辑' : '创建',
        nzContent: ModalComponent,
        nzMaskClosable: false,
        nzFooter: [
          {
            type: 'primary',
            label: '确定',
            disabled: instance => instance ? (instance.validateForm.invalid || !instance.validateForm.dirty) : true,
            onClick: () => ctx.dispatch(new ShopAction.Submit()),
          },
          {type: 'default', label: '取消', onClick: () => modalRef.triggerCancel()},
        ],
        nzOnCancel: () => {
          ctx.dispatch(new ShopAction.CloseModal());
        },
      });
    }));
  }

  @Action(ShopAction.Delete)
  Delete(ctx: StateContext<ShopStateModel>, {data}: ShopAction.Delete) {
    let state = ctx.getState();
    let idx = _.findIndex(state.list, (s: any) => s.id === data.id);
    ctx.setState(immutable.del(state, ['list', idx]));
  }

  @Action(ShopAction.AddToCart)
  AddToCart(ctx: StateContext<ShopStateModel>, {data}: ShopAction.AddToCart) {
    let state = ctx.getState();
    if (!!state.cart && data.id in state.cart) {
      let count = state.cart[data.id];
      ctx.setState(immutable.set(state, ['cart', data.id], count + 1));
    } else {
      ctx.setState(immutable.set(state, ['cart', data.id], 1));
    }
  }

  @Action(ShopAction.GotoCheckout)
  GotoCheckout(ctx: StateContext<ShopStateModel>) {
    let state = ctx.getState();
    let data = Object.keys(state.cart).map(s => {
      return {
        key: s,
        count: state.cart[s],
        data: _.find(state.list, a => a.id === s),
      };
    });
    return ctx.dispatch(new MessageAction.Send({key: 'Shop_GotoCheckout', data}));
  }

  @Action(ShopAction.ChangeCount)
  ChangeCount(ctx: StateContext<ShopStateModel>, {count, data}: ShopAction.ChangeCount) {
    let state = ctx.getState();
    if (count <= 0) {
      ctx.setState(immutable.del(state, ['cart', data.key]));
    } else {
      ctx.setState(immutable.set(state, ['cart', data.key], count));
    }
  }

  @Action(ShopAction.ClearCart)
  ClearCart(ctx: StateContext<ShopStateModel>) {
    ctx.patchState({cart: {}});
  }
}
